package cat.joronya.supermanager.service;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Hashtable;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HTTP;

import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.util.Log;
import cat.joronya.supermanager.Supermanager;
import cat.joronya.supermanager.market.Player;

/**
 * Recuperem el llistat de jugadors del mercat.
 * 
 * @author pol
 */
public class MarketSync 
{
	private static final String TAG = "supermanager";
	
	// el service
	private SupermanagerService service;
	
	// el client http on fer les peticions
	private DefaultHttpClient client = null;
	
	// jornada passada de loginSyn pq no es a les pagines de market
	private Integer jornada = null;
	
	// status de retorn
	public int status = -1;
	
	// market GET
	private static final String MARKET_GET = InitSync.BASE_URL+"/vermercado.php";
	
	// hash per guardar codi=>id_jug
	protected Hashtable<String, String> idJugPerCodi = null;
	
	// hash per guardar team vs team
	protected Hashtable<String, String> dayMatches = null;
	
	// dades extretes de les pagines
	public ArrayList<Player> guards;
	public ArrayList<Player> forwards;
	public ArrayList<Player> centers;
	public ArrayList<Player> players;
	
	/**
	 * Constructor amb el intentService que el crida.
	 * @param intentService
	 */
	public MarketSync(SupermanagerService service, DefaultHttpClient client, Integer jornada)
	{
		this.service = service;
		this.client = client;
		this.jornada = jornada;
		
		this.idJugPerCodi = new Hashtable<String, String>();
		this.dayMatches = new Hashtable<String, String>();
		
		this.guards = new ArrayList<Player>();
		this.forwards = new ArrayList<Player>();
		this.centers = new ArrayList<Player>();
	}
	
	// passem els partits de la setmana previament processats
	public void setDayMatches(Hashtable<String, String> dayMatches)
	{
		this.dayMatches = dayMatches;
	}
	
	// sync the three market players posistions
	public void sync()
	{
		try
		{
			// checkejem per connectivitat
			ConnectivityManager cm = (ConnectivityManager) service.getSystemService(Context.CONNECTIVITY_SERVICE);
			boolean online = cm.getActiveNetworkInfo().isConnectedOrConnecting();

			if( !online )
				throw new ConnectivityException();
			
			// parse guards
			sync(1);
			// parse forwards
			sync(2);
			// parse centers
			sync(3);
			
			// persist all players
			persistPlayers(Supermanager.Market.CONTENT_URI);

			// parsejat ok
	        status = Supermanager.MARKET_PARSED_OK;
	        Log.d(TAG, "MarketSync status: MARKET_PARSED_OK - "+status);
	        return;
		}
		catch(ConnectivityException ce){
			// error de connectivitat
			Log.d(TAG, "MarketSync status: CONNECTIVITY_ERROR_STATUS - "+status);
	        status = Supermanager.CONNECTIVITY_ERROR_STATUS;
	        return;
		}
		catch(ClosedChangesException cce)
		{
			// canvis tancats
			Log.d(TAG, "MarketSync status:CLOSED_CHANGES_STATUS - "+status);
			status = Supermanager.CLOSED_STATUS;
			return;
		}
		catch(Exception e){
			// altre error, notifiquem i anem offline
			Log.d(TAG, "MarketSync status: OTHER_ERROR_STATUS - "+status);
			status = Supermanager.OTHER_ERROR_STATUS;
	        return;
		}	
	}
	
	/**
	 * Parse the market players on position passed.
	 * @param position
	 * @throws Exception
	 */
	protected void sync(int position) throws Exception
	{
		// guards
		HttpGet plHttpGet = new HttpGet(MARKET_GET+"?id_pos="+position);
		HttpResponse response = client.execute(plHttpGet);
		
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		response.getEntity().writeTo(os);
		String marketPage = os.toString(HTTP.ISO_8859_1);
		
		String pos = Supermanager.GUARD_POSITION;
		switch(position)
		{
			case 1: 
				pos = Supermanager.GUARD_POSITION;
				break;
			case 2:
				pos = Supermanager.FORWARD_POSITION;
				break;
			case 3:
				pos = Supermanager.CENTER_POSITION;
				break;
		}
		
		//MarketParser parser = MarketParserProvider.getImpl(Package.getPackage("cat.joronya.supermanager.service.htmlcleanerImpl"));
		MarketParser parser = MarketParserProvider.getImpl(Package.getPackage("cat.joronya.supermanager.service.substrImpl"));
		Log.d(Supermanager.TAG, "Start parsing market page...");
		long elapsedTime = parser.parse(marketPage, jornada, pos);
		Log.d(Supermanager.TAG, "Stop parsing market page! Elapsed time: "+elapsedTime/1000);
		
		// get parsed guards
		switch(position)
		{
			case 1: 
				this.guards = parser.getPlayers();
				break;
			case 2:
				this.forwards = parser.getPlayers();
				break;
			case 3:
				this.centers = parser.getPlayers();
				break;
		}
		
	}
	
	/**
	 * Guardar les dades trobades a DB.
	 */
    protected void persistPlayers(Uri uri)
    {
    	// primer borrem jugadors de la jornada ja que quan es dona de baixa
    	// un jugador no ha d'estar disponible al market
    	Log.d(TAG,"Deleted market data for day "+jornada.toString());
    	service.getContentResolver().delete(Supermanager.Market.CONTENT_URI,
    			Supermanager.Market.DAY+" = ? ",
    			new String[]{jornada.toString()});
    	
    	// tractem cada jugador, bases
    	Log.d(TAG,"Parsed "+guards.size()+" guard players, going to insert");
    	for(Player p: this.guards)
    	{
    		// insert or update el player al market
    		insertOrUpdatePlayer(uri, p, Supermanager.GUARD_POSITION);
    	}
    	
    	// tractem cada jugador, alers
    	Log.d(TAG,"Parsed "+forwards.size()+" forward players, going to insert");
    	for(Player p: this.forwards)
    	{
    		// insert or update el player al market
    		insertOrUpdatePlayer(uri, p, Supermanager.FORWARD_POSITION);
    	}
    	
    	// tractem cada jugador, pivots
    	Log.d(TAG,"Parsed "+centers.size()+" center players, going to insert");
    	for(Player p: this.centers)
    	{
    		// insert or update el player al market
    		insertOrUpdatePlayer(uri, p, Supermanager.CENTER_POSITION);
    	}	
    }
    
    /**
	 * Insert or Update Player as needed.
	 * @param uri
	 * @param pl
	 * @return
	 */
	private String insertOrUpdatePlayer(Uri uri, Player p, String position) 
	{
		// Hack per no haver de borrar tota la taula per treure la UNIQUE
		// Com aqui no tenim el idjug posem el codi al seu lloc pq
		// el idjug nomes el tenim al buy market.
		if( this.idJugPerCodi.get(p.getCodi()) != null )
			p.setId(this.idJugPerCodi.get(p.getCodi()));
		else
			p.setId("FAKE"+p.getCodi());
		
		// setejem el vs_team parsejat per la jornada
		p.setVsTeam(this.dayMatches.get(p.getTeam()));
		
		// insertem player
		ContentValues values = new ContentValues();
		values.put(Supermanager.Market.CODI_PLAYER, p.getCodi());
		
		// si, canvis tancats no tenim id_pplayer
		if( p.getId() != null)
			values.put(Supermanager.Market.ID_PLAYER, p.getId());
		
		values.put(Supermanager.Market.POSITION, position);
		values.put(Supermanager.Market.DAY, p.getDay());
		values.put(Supermanager.Market.STATUS, p.getStatus());
		values.put(Supermanager.Market.NACIONALITY, p.getNacionality());
		values.put(Supermanager.Market.NAME, p.getName());
		values.put(Supermanager.Market.INFO, p.getInfo());
		values.put(Supermanager.Market.TEAM, p.getTeam());
		values.put(Supermanager.Market.VS_TEAM, p.getVsTeam());
		values.put(Supermanager.Market.BALANCE, p.getBalance());
		values.put(Supermanager.Market.AVERAGE, p.getAverage());
		values.put(Supermanager.Market.PRICE, p.getPrice());
		values.put(Supermanager.Market.MINUTES, p.getMinutes());
		values.put(Supermanager.Market.RATING, p.getRating());
		values.put(Supermanager.Market.RATING_LAST3_GAMES, p.getRatingLast3Games());
		values.put(Supermanager.Market.INCREASE_15, p.getIncrease15());
		values.put(Supermanager.Market.KEEP_PRICE, p.getKeepPrice());
		values.put(Supermanager.Market.DECREASE_15, p.getDecrease15());
		values.put(Supermanager.Market.SHOWN_IN_BUY, 0);
		values.put(Supermanager.Market.COLOR_IN_BUY, (String)null);
		
		Uri playerUri = Supermanager.Market.CONTENT_URI;
		String lastPathSegment = "0";
		
		Log.d(TAG, "Market update codi: "+p.getCodi()+", id: " + p.getId() + ", day: "
				+ p.getDay().toString());
		
		// si update no retorna 1 reg, llavors insert
		if (service.getContentResolver().update(
				uri,
				values,
				Supermanager.Market.CODI_PLAYER + " = ? AND "
						+ Supermanager.Market.DAY + " = ? ",
				new String[] { p.getCodi(), p.getDay().toString() }) == 0) {
			// altrement fem insert
			playerUri = service.getContentResolver().insert(uri, values);
			lastPathSegment = playerUri.getLastPathSegment();
			Log.d(TAG, "Market inserting player with codi jug [" + p.getCodi()
					+ "] with Uri [" + playerUri + "] lastPathSegment ["
					+ lastPathSegment + "]");
		} 
		else 
		{
			Cursor cursor = service.getContentResolver().query(
					Supermanager.Market.CONTENT_URI,
					Supermanager.Market.PROJECTION,
					Supermanager.Market.CODI_PLAYER + " = ? AND "
							+ Supermanager.Market.DAY + " = ? ",
					new String[] { p.getCodi(), p.getDay().toString() },
					Supermanager.Market.DEFAULT_SORT_ORDER);

			if (cursor.moveToFirst()) 
			{
				lastPathSegment = "" + cursor.getLong(0);
				playerUri = ContentUris.withAppendedId(
						Supermanager.Market.CONTENT_URI, cursor.getLong(0));
			}
			Log.d(TAG, "Market Updating player with id_jug [" + p.getName()
					+ "] with Uri [" + playerUri + "] lastPathSegment ["
					+ lastPathSegment + "]");
		}

		return lastPathSegment;
	}
}	
